﻿using BigEgg.Framework.UnitTesting;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BigEgg.Framework.Foundation;
using UnitTestDemo.Applications.Properties;
using System.Globalization;

namespace UnitTestDemo.Applications.Test
{
    [TestClass]
    public class AnimalTest
    {
        [TestMethod]
        public void ConstructorTest()
        {
            AssertHelper.ExpectedException<ArgumentException>(() => new MockAnimal(null, null));
            AssertHelper.ExpectedException<ArgumentException>(() => new MockAnimal("", ""));
            AssertHelper.ExpectedException<ArgumentException>(() => new MockAnimal("Monky", null));
            AssertHelper.ExpectedException<ArgumentException>(() => new MockAnimal("  ", null));
            AssertHelper.ExpectedException<ArgumentException>(() => new MockAnimal(null, "QiTianDaSheng"));
            AssertHelper.ExpectedException<ArgumentException>(() => new MockAnimal(null, "  "));
        }

        [TestMethod]
        public void CheckBaseImplementation()
        {
            MockAnimal animal = new MockAnimal("Monky", "QiTianDaSheng");

            Assert.IsFalse(animal.CanRead());

            AssertHelper.ExpectedException<ArgumentException>(() => animal.Read(""));
            AssertHelper.ExpectedException<ArgumentException>(() => animal.Read(" "));
            AssertHelper.ExpectedException<ArgumentException>(() => animal.Read(null));

            AssertHelper.ExpectedException<NotSupportedException>(() => animal.Read("document"));

            AssertHelper.ExpectedException<NotImplementedException>(() => animal.ReadCore(null));
        }

        [TestMethod]
        public void GeneralAnimalTest()
        {
            MockAnimal animal = new MockAnimal("Monky", "QiTianDaSheng");
            Assert.AreEqual("Monky", animal.AnimalType);
            Assert.AreEqual("QiTianDaSheng", animal.Name);
            Assert.AreEqual(Gender.Male, animal.Gender);

            Assert.AreNotEqual(string.Empty, animal.Validate());

            animal.Gender = Gender.Female;
            animal.Age = 500;
            Assert.AreEqual(Gender.Female, animal.Gender);
            Assert.AreEqual(500, animal.Age);
            Assert.AreEqual(string.Empty, animal.Validate());
        }

        [TestMethod]
        public void PropertiesWithNotification()
        {
            MockAnimal animal = new MockAnimal("Monky", "QiTianDaSheng");

            AssertHelper.PropertyChangedEvent(animal, x => x.Name, () => animal.Name = "BaiGuJing");
            AssertHelper.PropertyChangedEvent(animal, x => x.Gender, () => animal.Gender = Gender.Female);
            AssertHelper.PropertyChangedEvent(animal, x => x.Age, () => animal.Age = 500);
        }

        [TestMethod]
        public void NameValidationTest()
        {
            MockAnimal animal = new MockAnimal("Monky", "QiTianDaSheng");
            Assert.AreEqual(string.Empty, animal.Validate("Name"));

            animal.Name = TestHelper.CreateString('A', 51);
            Assert.AreEqual(
                string.Format(CultureInfo.CurrentCulture, Resources.NameMaxLength, "Namme", 50),
                animal.Validate("Name"));

            animal.Name = TestHelper.CreateString('A', 50);
            Assert.AreEqual(string.Empty, animal.Validate("Name"));

            animal.Name = string.Empty;
            Assert.AreEqual(
               string.Format(CultureInfo.CurrentCulture, Resources.NameMandatory),
               animal.Validate("Name"));
        }

        [TestMethod]
        public void AgeValidationTest()
        {
            MockAnimal animal = new MockAnimal("Monky", "QiTianDaSheng");
            Assert.AreNotEqual(string.Empty, animal.Validate("Age"));

            animal.Age = 1;
            Assert.AreEqual(string.Empty, animal.Validate("Age"));

            animal.Age = 0;
            Assert.AreEqual(
                string.Format(CultureInfo.CurrentCulture, Resources.AgeEqualOrLarger, "Age", 1),
                animal.Validate("Age"));
        }

        private class MockAnimal : Animal
        {
            public MockAnimal(string animalType, string name)
                : base(animalType, name)
            {
            }

            public void ReadCore(string document) { base.ReadCore(document); }
        }
    }
}
